package cn.wen.mybatis.framework.executor.statement;


import cn.wen.mybatis.framework.executor.Executor;
import cn.wen.mybatis.framework.mapping.BoundSql;
import cn.wen.mybatis.framework.mapping.MappedStatement;
import cn.wen.mybatis.framework.mapping.ResultSetType;
import cn.wen.mybatis.framework.session.ResultHandler;
import cn.wen.mybatis.framework.session.RowBounds;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;

/**
 * 简单的Statement处理器，Statement:用于执行静态 SQL 语句并返回它所生成结果的对象
 */
public class SimpleStatementHandler extends BaseStatementHandler {

    /**
     * @param executor        执行器
     * @param mappedStatement Mapper.xml文件的select,delete,update,insert这些DML标签的封装类
     * @param parameter       参数对象
     * @param rowBounds       Mybatis的分页对象
     * @param resultHandler   结果处理器
     * @param boundSql        参数映射与可执行SQL封装类对象
     */
    public SimpleStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
        super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
    }

    @Override
    public int update(Statement statement) throws SQLException {
        // 获取SQL脚本
        String sql = boundSql.getSql();

        // 获取参数对象
        Object parameterObject = boundSql.getParameterObject();
        // 已更新的函数
        int rows;
        //执行SQL
        statement.execute(sql);
        //获取更新记录数
        rows = statement.getUpdateCount();
        return rows;
    }

    /**
     * 批处理，只是获取boundSql的可执行SQL，然后添加到 {@code statment}
     *
     * @param statement 执行 SQL 语句并返回它所生成结果的对象
     */
    @Override
    public void batch(Statement statement) throws SQLException {
        //获取可执行SQL
        String sql = boundSql.getSql();
        //添加批处理队列中
        statement.addBatch(sql);
    }

    /**
     * 用于通知Statement将[select]推送到数据库并返回对应查询结果
     *
     * @param statement     执行 SQL 语句并返回它所生成结果的对象
     * @param resultHandler 结果处理器
     * @param <E>           结果对象类型
     * @return
     */
    @Override
    public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
        //获取可执行SQL
        String sql = boundSql.getSql();
        //执行SQL
        statement.execute(sql);
        //处理 statement 中的所有结果集，返回结果对象集合
        return resultSetHandler.handleResultSets(statement);
    }

    /**
     * 实例化Statement对象
     *
     * @param connection 数据库连接
     * @return 执行 SQL 语句并返回它所生成结果的对象
     */
    @Override
    protected Statement instantiateStatement(Connection connection) throws SQLException {
        //ResultSetType.DEFAULT:表示依赖驱动进行创建Statement实例
        if (mappedStatement.getResultSetType() == ResultSetType.DEFAULT) {
            //创建一个 Statement 对象来将 SQL 语句发送到数据库
            return connection.createStatement();
        } else {
            /**
             * ResultSetType.FORWARD_ONLY:结果集的游标只能向下滚动
             * ResultSetType.SCROLL_INSENSITIVE:结果集的游标可以上下移动，当数据库变化时，当前结果集不变
             * ResultSetType.SCROLL_SENSITIVE:返回可滚动的结果集，当数据库变化时，当前结果集同步改变
             *
             * ResultSet.CONCUR_READ_ONLY:不能用结果集更新数据库中的表。
             * ResultSet.CONCUR_UPDATABLE:能用结果集更新数据库中的表
             */
            //创建一个 Statement 对象，该对象将生成具有给定类型和并发性的 ResultSet 对象。
            return connection.createStatement(mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
        }
    }

    @Override
    public void parameterize(Statement statement) {
        // N/A N/A是Not Applicable 的缩写,表示“不适用”的意思
    }


}
